import type { Tab } from '#/browser/entities/tab.entity'

import type { SeparateWindowManager } from '#/browser/managers/separateWindow.manager'

import { WebContents } from 'electron'
/**
 * @file 标签页管理器
 * @description 负责协调和管理多个标签页控制器，处理标签页的统一管理和事件分发
 * @author 黄敏
 * @since 2025-08-23 15:24
 */
import { TabController } from '#/browser/controllers/tab.controller'
import { TypedEventEmitter } from '#/utils/events'
import { createBrowserIpc } from '#/utils/ipc'

type Events = {
  'view-changed': (type: F2.tab.ControllerType) => void // 视图发生变化时触发，包含标签页信息
}

/**
 * 标签页管理器
 *
 * 负责协调和管理多个标签页控制器（top/left/right），
 * 处理标签页的统一管理、事件分发和视图切换
 */
export class TabManager extends TypedEventEmitter<Events> {
  layoutTab: Tab
  private browserIpc!: ReturnType<typeof createBrowserIpc>

  /** 标签页控制器实例，负责标签页的业务逻辑管理 */
  readonly topTabController: TabController
  /** 左侧边栏标签页控制器实例，负责边栏标签页的业务逻辑管理, 只在主浏览器中存在 */
  readonly leftTabController?: TabController

  /** 右侧边栏标签页控制器实例，负责边栏标签页的业务逻辑管理 */
  readonly rightTabController: TabController

  /** 当前激活的标签页ID，topTabController和leftTabController共用该id */
  private activeTabId = 0
  /** 当前激活的右侧边栏标签页ID */
  private activeRightTabIds: number[] = []

  // 独立窗口管理器
  separateWindowManager: SeparateWindowManager

  isMainWindow: boolean

  /** 窗口关闭回调函数 */
  private windowCloseCallback?: () => void

  get activeTab(): { tab: Tab; type: F2.tab.MainControllerType } | void {
    if (this.activeTabId) {
      let tab = this.topTabController.getTabById(this.activeTabId)
      if (tab) {
        return {
          tab,
          type: 'top'
        }
      }

      tab = this.leftTabController?.getTabById(this.activeTabId)
      if (tab) {
        return {
          tab,
          type: 'left'
        }
      }
    } else {
      return void 0
    }
  }

  get activeRightTabs(): Tab[] {
    return this.activeRightTabIds
      .map(id => this.rightTabController.getTabById(id))
      .filter(Boolean) as Tab[]
  }

  /**
   * 发送消息到渲染进程
   */

  constructor({
    isMainWindow,
    data,
    layoutTab,
    separateWindowManager
  }: {
    isMainWindow: boolean
    layoutTab: Tab
    separateWindowManager: SeparateWindowManager
    data?: Tab[] | string
  }) {
    super()
    this.isMainWindow = isMainWindow
    this.layoutTab = layoutTab
    this.browserIpc = createBrowserIpc(this.layoutTab.view.webContents)

    this.separateWindowManager = separateWindowManager
    this.topTabController = this.createTopTabController(data)
    this.leftTabController = this.createSidebarController('left')
    this.rightTabController = this.createSidebarController('right')
  }

  createTopTabController(data?: Tab[] | string) {
    // 初始化顶部标签页控制器
    const topTabController = new TabController(this.isMainWindow ? [] : data, 'top')

    this.commonEvent(topTabController, 'top')

    return topTabController
  }

  createSidebarController(type: 'left' | 'right') {
    // 初始化边栏标签页控制器
    const sidebarTabController = new TabController([], type)

    this.commonEvent(sidebarTabController, type)

    return sidebarTabController
  }

  getControllerByType(type: F2.tab.ControllerType): TabController | void {
    if (type === 'left') {
      return this.leftTabController
    } else if (type === 'right') {
      return this.rightTabController
    } else {
      return this.topTabController
    }
  }

  createTabs(type: F2.tab.ControllerType, tabParams?: F2.tab.CreateInput) {
    const controller = this.getControllerByType(type)
    if (!controller) return
    const activeTab = controller.createTabs(tabParams)
    if (activeTab) this.setActive(type, activeTab)
  }

  commonEvent(tabController: TabController, type: F2.tab.ControllerType) {
    tabController.on('tab:create', tabParams => {
      this.createTabs('top', [tabParams])
    })

    tabController.on('tab-data:created', tabs => {
      this.browserIpc.send(`${type}:created`, tabs)
    })

    tabController.on('tab-data:update', data => {
      this.browserIpc.send(`${type}:update`, data)
    })

    tabController.on('tab:inited', data => {
      this.browserIpc.send(`${type}:inited`, data.data.id)
    })

    tabController.on('tab:closed', tabIds => {
      this.browserIpc.send(`${type}:close`, tabIds)
      // 监听标签页全部关闭事件，如果不是主浏览器，则通知父窗口关闭
      if (tabController.tabCount === 0 && type === 'top' && !this.isMainWindow) {
        this.windowCloseCallback?.()
      }

      if (tabController.type === 'right') {
        this.clearActiveRight(tabIds)
      } else {
        // 主界面的活动标签页选择让渲染进程来处理，这里不处理
      }
    })

    tabController.on('tab:active', tab => {
      this.setActive(type, tab)
    })
  }

  getControllerByTabId(id: number): TabController | void {
    if (this.topTabController.tabInstances.has(id)) return this.topTabController
    else if (this.rightTabController.tabInstances.has(id)) return this.rightTabController
    else if (this.leftTabController?.tabInstances.has(id)) return this.leftTabController
    else return void 0
  }

  onCloseTabsById(tabIds: number[]) {
    if (tabIds.length === 0) return
    const controller = this.getControllerByTabId(tabIds[0])
    if (controller) {
      controller?.closeTabsById(tabIds)
    }
  }

  /**
   * 隐藏指定的标签页
   * */
  hideTabById(tabId: number) {
    const controller = this.getControllerByTabId(tabId)
    if (controller) {
      if (controller.type === 'right') {
        this.clearActiveRight([tabId])
      } else if (this.activeTabId === tabId) {
        this.clearActive()
      }
    }
  }

  /**
   * 切换到指定的标签页
   *
   * @param tabId - 要切换到的标签页ID, 如果未指定则删除活动标签页
   * @throws Error 如果标签页不存在
   *
   * @description 移除当前所有视图，激活目标标签页并更新活动状态
   */
  onSwitch(tabId: number): void {
    try {
      let type: F2.tab.ControllerType = 'top'

      let targetTabInstance = this.topTabController.getTabById(tabId)

      if (!targetTabInstance && this.leftTabController) {
        targetTabInstance = this.leftTabController.getTabById(tabId)
        type = 'left'
      }

      if (!targetTabInstance) {
        targetTabInstance = this.rightTabController.getTabById(tabId)
        type = 'right'
      }

      if (!targetTabInstance) {
        console.warn(`标签页 ${tabId} 不存在，无法切换`)
        return
      }

      if (targetTabInstance) {
        this.setActive(type, targetTabInstance)
      }
    } catch (error) {
      console.error(`切换标签页 ${tabId} 时发生错误:`, error)
    }
  }

  /** 取消活动状态 */
  clearActive() {
    this.activeTabId = 0
    this.browserIpc.send('switch', 0)
    this.emit('view-changed', 'top')
  }

  /**
   * 取消右侧指定的活动标签页
   * @param tabIds - 要取消活动状态的标签页ID数组
   * */
  clearActiveRight(tabIds: number[]) {
    if (this.activeRightTabIds.some(id => tabIds.includes(id))) {
      this.activeRightTabIds = this.activeRightTabIds.filter(id => !tabIds.includes(id))
      this.browserIpc.send('right:switch', this.activeRightTabIds)
      this.emit('view-changed', 'right')
    }
  }

  /**
   * 切换到指定的标签页
   * @param type - 标签页类型
   * @param tab - 要切换到的标签页对象
   * */
  setActive(type: F2.tab.ControllerType, tab: Tab) {
    let hasSeparateWindowOpen = false
    if (type !== 'top' && tab.data.isInSeparateWindow) {
      this.separateWindowManager.openWindow(tab, type)
      hasSeparateWindowOpen = true
    } else if (this.separateWindowManager.isWindowOpen(tab.data.id)) {
      const window = this.separateWindowManager.getWindow(tab.data.id)
      window?.close()
    }

    if (type === 'right') {
      if (!hasSeparateWindowOpen || this.activeRightTabIds.includes(tab.data.id)) {
        if (hasSeparateWindowOpen) {
          this.clearActiveRight([tab.data.id])
        } else {
          const newIds = this.activeRightTabs.filter(t => t.isPinned).map(v => v.id)
          if (!newIds.includes(tab.data.id)) {
            newIds.unshift(tab.data.id)
          }
          this.activeRightTabIds = newIds
          this.browserIpc.send('right:switch', this.activeRightTabIds)
        }
      }
    } else {
      if (!hasSeparateWindowOpen || this.activeTabId === tab.data.id) {
        this.activeTabId = hasSeparateWindowOpen ? 0 : tab.data.id
        this.browserIpc.send('switch', this.activeTabId)
      }
    }

    // 通知上层进行视图切换
    this.emit('view-changed', type)
  }

  /**
   * 获取当前激活的标签页ID
   * @returns 当前激活标签页的ID
   */
  getActiveTabId() {
    return this.activeTabId
  }

  /**
   * 获取当前激活的右侧标签页ID
   * @returns 当前激活右侧标签页的ID
   */
  getActiveRightTabId() {
    this.browserIpc.send('right:switch', this.activeRightTabIds)
  }

  // 创建标签页分组
  createTabGroup(urls: string[]) {
    this.browserIpc.send('group:create', urls)
  }

  /**
   * 检查当前浏览器是否包含指定的WebContents
   *
   * @param webContents - 要检查的WebContents实例
   * @returns 如果当前浏览器包含该WebContents则返回true，否则返回false
   *
   * @description 用于确定WebContents的归属，包括布局视图和标签页视图
   */
  getTabByWebContents(webContents: WebContents): boolean {
    if (this.topTabController.getTabByWebContents(webContents)) return true
    return !!this.rightTabController.getTabByWebContents(webContents)
  }

  /**
   * 设置窗口关闭回调函数
   * @param callback 窗口关闭时执行的回调函数
   */
  setWindowCloseCallback(callback: () => void) {
    this.windowCloseCallback = callback
  }

  /**
   * 销毁该实例
   * */
  destroy() {
    this.topTabController.destroy()
    this.leftTabController?.destroy()
    this.rightTabController.destroy()
    this.removeAllListeners()
  }
}
